package com.ruoyi.warning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.warning.domain.entity.*;
import com.ruoyi.warning.domain.query.FirewallQuery;
import com.ruoyi.warning.mapper.FirewallMapper;
import com.ruoyi.warning.service.*;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * <p>
 * 防火墙相关 服务实现类
 * </p>
 *
 * @author chenhc
 * @since 2025-07-23
 */
@Service
public class FirewallServiceImpl extends ServiceImpl<FirewallMapper, Firewall> implements IFirewallService {
    @Resource
    private IDevicesService devicesService;
    @Resource
    private IFirewallLogService firewallLogService;
    @Resource
    private IPortsService portsService;
    @Resource
    private IPortsCriticalLogService portsCriticalLogService;
    @Resource
    private FirewallMapper firewallMapper;
    @Resource
    private IConfigService configService;

    @Override
    public Object addFirewall(String hostname) {
        Device device = devicesService.getOne(new QueryWrapper<Device>().lambda().eq(Device::getHostname,hostname).last("limit 1"));
        if(ObjectUtils.isEmpty(device)){
            return null;
//            throw new ServiceException("请先添加设备");
        }
        Firewall firewall = new Firewall();
        firewall.setDeviceId(device.getDeviceId());
        firewall.setHostname(hostname);
        firewall.setName(getCmdString(".1.3.6.1.2.1.1.5.0",device));
        firewall.setSerial(getCmdString(".1.3.6.1.4.1.12356.100.1.1.1.0",device));
        String time = getCmdString(".1.3.6.1.2.1.1.3.0",device);
        firewall.setRuntime(time.substring(time.indexOf(")")+2));
        firewall.setVersion(getCmdString(".1.3.6.1.4.1.12356.101.4.1.1.0",device));
        firewall.setCpuCount(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.5.3.1.5.1",device)));
        firewall.setTotalCpuUtilization(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.3.0",device)));
        firewall.setMemoryUtilization(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.4.0",device)));
        firewall.setTotalMemorySize(Long.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.5.0",device)));
        firewall.setConcurrentConnectionsCount(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.8.0",device)));
        firewall.setNewConnections1m(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.11.0",device)));
        firewall.setNewConnections10m(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.12.0",device)));
        firewall.setNewConnections30m(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.13.0",device)));
        firewall.setNewConnections60m(Integer.valueOf(getCmdString(".1.3.6.1.4.1.12356.101.4.1.14.0",device)));
        firewall.setLicenceExpirationTime(getCmdString(".1.3.6.1.4.1.12356.101.4.6.3.1.2.1",device));
        firewall.setProtocolErrorLoss(Integer.valueOf(getCmdString(".1.3.6.1.2.1.4.4.0",device)));
        firewall.setDeviceId(device.getDeviceId());
        firewall.setUpdateTime(LocalDateTime.now());
        Firewall firewall1 = this.getOne(new QueryWrapper<Firewall>().lambda().eq(Firewall::getHostname,hostname).last("limit 1"));
        if(firewall1 != null){
            firewall.setFirewallId(firewall1.getFirewallId());
        }

        FirewallLog firewallLog = new FirewallLog();
        BeanUtils.copyProperties(firewall,firewallLog);
        firewallLog.setLogId(UUID.randomUUID().toString().replace("-",""));
        firewallLog.setCreateTime(LocalDateTime.now());

        //根据deviceid查询端口
        List<Port> portsList = portsService.list(new QueryWrapper<Port>().lambda()
                .eq(Port::getDeviceId,device.getDeviceId())
                .orderByAsc(Port::getIfIndex));
        List<String> ifInLossList = getCmdList(".1.3.6.1.2.1.2.2.1.13", device);
        List<String> ifOutLossList = getCmdList(".1.3.6.1.2.1.2.2.1.19", device);
        List<String> ifInNoUnicastForwardList = getCmdList(".1.3.6.1.2.1.2.2.1.12", device);
        List<String> ifOutNoUnicastForwardList = getCmdList(".1.3.6.1.2.1.2.2.1.18", device);
        List<String> ifUnknownDropList = getCmdList(".1.3.6.1.2.1.2.2.1.15", device);
        List<PortsCriticalLog> portsCriticalLogList = new ArrayList<>();
        for(int i=0;i<portsList.size();i++){
            Port port = portsList.get(i);
            port.setIfInLoss(Long.valueOf(ifInLossList.get(i)));
            port.setIfOutLoss(Long.valueOf(ifOutLossList.get(i)));
            port.setIfInNoUnicastForward(Long.valueOf(ifInNoUnicastForwardList.get(i)));
            port.setIfOutNoUnicastForward(Long.valueOf(ifOutNoUnicastForwardList.get(i)));
            port.setIfUnknownDrop(Long.valueOf(ifUnknownDropList.get(i)));
            if(port.getIsCritical()==1){
                PortsCriticalLog portsCriticalLog = new PortsCriticalLog();
                BeanUtils.copyProperties(port,portsCriticalLog);
                portsCriticalLog.setIfSpeed(port.getIfSpeed());
                portsCriticalLog.setIfPhysAddress(port.getIfPhysAddress());
                portsCriticalLog.setIfVlan(port.getIfVlan());
                portsCriticalLog.setCreateTime(LocalDateTime.now());
                portsCriticalLog.setPortId(port.getPortId());
                portsCriticalLogList.add(portsCriticalLog);
            }
        }
        portsService.updateBatchById(portsList);
        if(!ObjectUtils.isEmpty(portsCriticalLogList)){
            portsCriticalLogService.saveBatch(portsCriticalLogList);
        }
        this.saveOrUpdate(firewall);
        firewallLogService.save(firewallLog);
        return "添加成功";
    }


    @Override
    public List<LinkedHashMap<String, Object>> getping(FirewallQuery query) {
        Config config = configService.getOne(new QueryWrapper<Config>().lambda().eq(Config::getConfigName,"ping_monitor"));
        if(ObjectUtils.isEmpty(config))return null;
        String[] list1 = config.getConfigValue().split(",");
        List<LinkedHashMap<String, Object>> list = firewallMapper.getPingExcel(list1,query.getStartTime(),query.getEndTime());
        System.out.println( list);
        return list;
    }

    private String getCmdString(String oid,Device device){
        String result = "";
        try {
            // 构建命令数组（避免空格分割问题）
            String[] cmd = {"snmpwalk", "-"+device.getSnmpver(), "-c", device.getCommunity(), device.getHostname(), oid};
            // 创建进程
            Process process = Runtime.getRuntime().exec(cmd);
            // 读取标准输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("++++++++++++++++++++");
                System.out.println(line);
                // 找到第一个 ": " 的位置
                int index = line.indexOf(": ");
                if (index != -1) {
                    // 从 ": " 之后截取字符串
                    result = line.substring(index + 2);
                    // 去掉双引号
                    result = result.replace("\"", "");
                }
            }
            // 读取错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.out.println("=====================");
                System.err.println(line);
                return null;
            }
            // 等待进程结束并获取退出码
            int exitCode = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private List<String> getCmdList(String oid, Device device){
        List<String> list = new ArrayList<>();
        try {
            // 构建命令数组（避免空格分割问题）
            String[] cmd = {"snmpwalk", "-v2c", "-c", device.getCommunity(), device.getHostname(), oid};
            // 创建进程
            Process process = Runtime.getRuntime().exec(cmd);
            // 读取标准输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            int index;
            while ((line = reader.readLine()) != null) {
                System.out.println("++++++++++++++++++++");
                System.out.println(line);
                // 找到第一个 ": " 的位置
                index = line.indexOf(": ");
                if (index != -1) {
                    // 从 ": " 之后截取字符串
                    line = line.substring(index + 2);
                    // 去掉双引号
                    list.add(line.replace("\"", ""));
                }
            }
            // 读取错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.out.println("=====================");
                System.err.println(line);
                return null;
            }
            // 等待进程结束并获取退出码
            int exitCode = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


}
